﻿using System;
using System.IO;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Navigation;
using System.ComponentModel;
using System.Deployment.Application;

namespace BadHabit.Factory.Controls {

    /// <summary>
    /// ListBox UserControl for a Project Dataset.
    /// </summary>
	public partial class ProjectListBox {


        #region SelectedProjectChanged Event

        // register the routed event
        public static readonly RoutedEvent SelectedProjectChangedEvent =
            EventManager.RegisterRoutedEvent("SelectedProjectChanged", RoutingStrategy.Bubble, typeof(SelectedProjectChangedEventHandler), typeof(ProjectListBox));

        // the event handler
        public delegate void SelectedProjectChangedEventHandler(object sender, SelectedProjectChangedEventArgs e);

        /// <summary>
        /// Occurs when the selected project was changed.
        /// </summary>
        public event SelectedProjectChangedEventHandler SelectedProjectChanged {
            add { AddHandler(SelectedProjectChangedEvent, value); }
            remove { RemoveHandler(SelectedProjectChangedEvent, value); }
        }

        /// <summary>
        /// Raises the SelectedProjectEvent.
        /// </summary>
        private void RaiseSelectedProjectChangedEvent() {
            Data.ProjectDataSet.ProjectRow project = Helper.GetRowFromRowView<Data.ProjectDataSet.ProjectRow>(listBox.SelectedItem);
            SelectedProjectChangedEventArgs newEventArgs = new SelectedProjectChangedEventArgs(project);
            newEventArgs.RoutedEvent = ProjectListBox.SelectedProjectChangedEvent;
            RaiseEvent(newEventArgs);
        }

        /// <summary>
        /// Class with arguments for the SelecetedProjectChangedEvent.
        /// </summary>
        public class SelectedProjectChangedEventArgs : RoutedEventArgs {
            public Data.ProjectDataSet.ProjectRow NewProject { get; private set; }
            public SelectedProjectChangedEventArgs(Data.ProjectDataSet.ProjectRow projectRow) {
                NewProject = projectRow;
            }
        }

        #endregion



        public object PreviousSelectedItem { get; private set; }

        private string[] clientFilterList = null;

        ListCollectionView collectionView = null; // the collection used to filter

        WPFTools.DelayFilter delayFilter;

        // this is a key for the SelectedProject property
        internal static readonly DependencyPropertyKey SelectedProjectKey =
            DependencyProperty.RegisterReadOnly("SelectedProject",
            typeof(Data.ProjectDataSet.ProjectRow),
            typeof(ProjectListBox),
            new PropertyMetadata(null)
        );
        // this is a key for the ProjectsCount property
        internal static readonly DependencyPropertyKey ProjectsCountKey =
            DependencyProperty.RegisterReadOnly("ProjectsCount",
            typeof(int),
            typeof(ProjectListBox),
            new PropertyMetadata(null)
        );

        /// <summary>
        /// DP property for the SelectedProject.
        /// </summary>
        public static readonly DependencyProperty SelectedProjectProperty = SelectedProjectKey.DependencyProperty;

        /// <summary>
        /// Gets the selected project.
        /// </summary>
        public Data.ProjectDataSet.ProjectRow SelectedProject {
            get { return (Data.ProjectDataSet.ProjectRow)GetValue(SelectedProjectProperty); }            
        }

        /// <summary>
        /// DP property for the ProjectsCount.
        /// </summary>
        public static readonly DependencyProperty ProjectsCountProperty = ProjectsCountKey.DependencyProperty;

        /// <summary>
        /// Gets the number of projects.
        /// </summary>
        public int ProjectsCount {
            get { return (int)GetValue(ProjectsCountProperty); }
        }
        
        /// <summary>
        /// Default constructor.
        /// </summary>
		public ProjectListBox()		{
			this.InitializeComponent();            
			// Insert code required on object creation below this point. 
            SetValue(SelectedProjectKey, null);

            delayFilter = new BadHabit.WPFTools.DelayFilter(1, ApplyFilter);
            

		}
       
        /// <summary>
        /// Every time the datacontext change, creates a collection view to the new context.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void UserControl_DataContextChanged(object sender, DependencyPropertyChangedEventArgs e) {

            // if the new context is not what it supposed to be            
            Data.ProjectDataSet.ProjectDataTable projectsTable = DataContext as Data.ProjectDataSet.ProjectDataTable;
            if (projectsTable == null)
                return;

            collectionView = new ListCollectionView(projectsTable.DefaultView);
            collectionView.Filter = IsInFilter;

            //DataContext = collectionView;
            listBox.ItemsSource = collectionView;

            
                        
        }

        /// <summary>
        /// Every time the text change, applies the filter
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void projectFilterTextBox_TextChanged(object sender, TextChangedEventArgs e) {
            delayFilter.StartFilter();
        }

        private bool IsInFilter(object obj) {
            Data.ProjectDataSet.ProjectRow project = Helper.GetRowFromRowView<Data.ProjectDataSet.ProjectRow>(obj);
                
            // applies the client filter
            string clientFilter = "";
            if (!String.Empty.Equals(clientFilterComboBox.SelectedValue) && clientFilterComboBox.SelectedValue!=null) {
                clientFilter = clientFilterComboBox.SelectedValue.ToString();
                if (!project.ClientName.Contains(clientFilter))
                    return false;
            }

            // applies the textbox filter
            if (projectFilterTextBox.Text != null && !String.Empty.Equals(projectFilterTextBox.Text)) {
                string text = projectFilterTextBox.Text.ToUpper();
                int projectNumber;
                if (!Int32.TryParse(text, out projectNumber))
                    projectNumber = -1;
                
                if(!project.ProjectName.ToUpper().Contains(text) &&
                   !project.ClientName.ToUpper().Contains(text) &&
                   !project.ProjectNumber.Equals(projectNumber))
                    return false;

            }

            return true;
            
        }

        
        /// <summary>
        /// When project filter changes, rebind the project from the service.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void projectFilterComboBox_SelectionChanged(object sender, SelectionChangedEventArgs e) {
            Bind();
            BadHabit.Factory.Properties.Settings.Default.ProjectFilterSelectedIndex = projectFilterComboBox.SelectedIndex;      
        }

        /// <summary>
        /// Binds the project from the server with the control.
        /// </summary>
        public void Bind() {

            if (Client.Service == null)
                return;

            if (!Client.IsConnected)
                return;

            Data.ProjectDataSet projectDataSet = new BadHabit.Factory.Data.ProjectDataSet();
            ComboBoxItem selectedItem = (ComboBoxItem) projectFilterComboBox.SelectedItem;
            try {
                if (projectsImInComboBoxItem.Equals(selectedItem))
                    projectDataSet.Merge(Client.Service.RetriveTeamMemberProjects(Client.User.Identity.Name));
                if (taskForMeProjectsComboBoxItem.Equals(selectedItem))
                    projectDataSet.Merge(Client.Service.RetriveToDoProjectsProjects(Client.User.Identity.Name));
                
                if (runningProjectsComboBoxItem.Equals(selectedItem))
                    projectDataSet.Merge(Client.Service.RetriveRunningProjects());
                if (allProjectsComboBoxItem.Equals(selectedItem))
                    projectDataSet.Merge(Client.Service.RetriveAllProjects());
                if (scheduledProjectsComboBoxItem.Equals(selectedItem))
                    projectDataSet.Merge(Client.Service.RetriveScheduledProjects());
                if (oportunitesProjectsComboBoxItem.Equals(selectedItem))
                    projectDataSet.Merge(Client.Service.RetriveOportunitiesProjects());
                if (closedProjectsComboBoxItem.Equals(selectedItem))
                    projectDataSet.Merge(Client.Service.RetriveClosedProjects());
                if (stillToPayProjectsComboBoxItem.Equals(selectedItem))
                    projectDataSet.Merge(Client.Service.RetriveStillToPayProjects());
                if (inDebitProjectsComboBoxItem.Equals(selectedItem))
                    projectDataSet.Merge(Client.Service.RetriveInDebitProjects());
            } catch (Exception ex) {
                Windows.Error.ShowError(ex, "Sorry, could not read projects");
                return;
            }
            

            Bind(projectDataSet);

            ShowHideNoProjectGrid();

        }


        private bool IsBinding { get; set; }
        public void Bind(Data.ProjectDataSet projectDataSet) {

            IsBinding = true;

            UpdateClientFilterList(projectDataSet);
            DataContext = projectDataSet.Project;
            
            IsBinding = false;

            SetValue(ProjectsCountKey, collectionView.Count);

        }

        /// <summary>
        /// Notify the SelectedProject dependency property of changes.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void listBox_SelectionChanged(object sender, SelectionChangedEventArgs e) {

            if (IsBinding) {
                if (listBox.Items.Contains(PreviousSelectedItem))
                    listBox.SelectedItem = PreviousSelectedItem;
                else
                    listBox.SelectedItem = null;
                e.Handled = true;
                return;
            }

            if (e.AddedItems.Count > 0)
                PreviousSelectedItem = e.AddedItems[0];

            SetValue(SelectedProjectKey, Helper.GetRowFromRowView<Data.ProjectDataSet.ProjectRow>(listBox.SelectedItem));

            RaiseSelectedProjectChangedEvent();

            //headerBorder.IsChecked = true;

            // reset the clock
            Controls.TaskPanelBase taskPanel = Client.FactoryMainWindow.tabControl.taskTabItem.Content as Controls.TaskPanelBase;
            if (taskPanel != null)
                taskPanel.TaskToolBar.timer.Reset();

        }
        
        /// <summary>
        /// Updates the list of distinct clients.
        /// </summary>
        private void UpdateClientFilterList(Data.ProjectDataSet project) {                        
            if (project == null)
                return;

            System.Data.DataTable distinctClient = project.Project.DefaultView.ToTable(true, "ClientName");
            clientFilterList = new string[distinctClient.Rows.Count + 1];            
            int i = 1;
            clientFilterList[0] = "";
            foreach (System.Data.DataRow r in distinctClient.Select("","ClientName")) {                
                clientFilterList[i] = r["ClientName"].ToString();
                i++;
            }

            clientFilterComboBox.ItemsSource = clientFilterList;

            
        }

        /// <summary>
        /// After a selection, applies the filter.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void clientFilterComboBox_SelectionChanged(object sender, SelectionChangedEventArgs e) {
            delayFilter.StartFilter();
        }


        /// <summary>
        /// After a filter selection, want to move the focus back to the list.        
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void filterComboBox_DropDownClosed(object sender, EventArgs e) {            
            listBox.Focus();
        }

 
        //private void goToRespositoryToolTip_MouseLeftButtonUp(object sender, System.Windows.Input.MouseButtonEventArgs e) {
        //    FrameworkElement c = sender as FrameworkElement;
        //    Data.ProjectDataSet.ProjectRow project = Helper.GetRowFromRowView<Data.ProjectDataSet.ProjectRow>(c.DataContext);
        //    Helper.OpenOSWindow(project.ProjectDocBase);
        //}


        private void CopyShortCut_Click(object sender, RoutedEventArgs e) {
            if(!ApplicationDeployment.IsNetworkDeployed)
                return;

            MenuItem item = sender as MenuItem;
            if (item == null)
                return;

            Data.ProjectDataSet.ProjectRow project = Helper.GetRowFromRowView<Data.ProjectDataSet.ProjectRow>(item.DataContext);
            if (project == null)
                return;
                       
            
            string projectShortCut = ApplicationDeployment.CurrentDeployment.UpdateLocation.AbsoluteUri;
            projectShortCut = projectShortCut + "?ProjectNumber=" + project.ProjectNumber; 
            Clipboard.SetText(projectShortCut);
        }



        private void ApplyFilter() {
            
            ListCollectionView view = listBox.ItemsSource as ListCollectionView;
            if (view == null)
                return;

            IsBinding = true;
            view.Refresh();
            IsBinding = false;


            SetValue(ProjectsCountKey, collectionView.Count);
            ShowHideNoProjectGrid();
            

        }

        private void ShowHideNoProjectGrid() {
            if (listBox.Items.Count == 0)
                noProjectFoundGrid.Visibility = Visibility.Visible;
            else
                noProjectFoundGrid.Visibility = Visibility.Hidden;
        }

        
        private void New_Executed(object sender, System.Windows.Input.ExecutedRoutedEventArgs e) {
            Client.FactoryMainWindow.CreateNewProject(Client.CreateNewProject());
        }

        private void UserControl_Loaded(object sender, RoutedEventArgs e) {          

            projectFilterComboBox.SelectedIndex = Properties.Settings.Default.ProjectFilterSelectedIndex;
            projectFilterTextBox.Focus();            
        }

        private void Grid_MouseLeftButtonUp(object sender, System.Windows.Input.MouseButtonEventArgs e) {
            if(listBox.SelectedItem!=null)
                headerBorder.IsChecked = true;
            
        }


        private void TextBlock_PreviewMouseLeftButtonDown(object sender, System.Windows.Input.MouseButtonEventArgs e) {
            FrameworkElement c = sender as FrameworkElement;
            Data.ProjectDataSet.ProjectRow project = Helper.GetRowFromRowView<Data.ProjectDataSet.ProjectRow>(c.DataContext);
            Helper.OpenOSWindow(project.ProjectDocBase);
        }



    }

   

}